// Локальные
#include "approximation/interpolation.h"

namespace approximation
{
    //============================================================================================================================
    //============================================================================================================================
    QList<double> Interpolation::interpolate(const QList<double> &arguments, const QList<double> &values, const QList<double> &points, Algorithm algorithm)
    {
        QList<double> interpolated_values;

        switch(algorithm)
        {
        case Linear:
            interpolated_values = linearInterpolation(arguments, values, points);
            break;
        default:
            qWarning("Unknown algorithm");
        }
        return interpolated_values;
    }

    //============================================================================================================================
    //============================================================================================================================
    QList< QVector<double> > Interpolation::interpolate(const QList<double> &arguments, const QList<double> &values, int num_of_points, Algorithm algorithm)
    {
        QList<double> points;
        for(int i = 0; i < num_of_points; i++)
            points.append(arguments.first() + (i + 1)*(arguments.last() - arguments.first())/(num_of_points + 1));

        QList<double> interpolated_values = interpolate(arguments, values, points, algorithm);

        QList< QVector<double> > result;
        for(int i = 0; i < points.size(); ++i)
        {
            result.append(QVector<double>(2));
            result.last()[0] = points[i];
            result.last()[1] = interpolated_values[i];
        }
        return result;
    }

    //============================================================================================================================
    //============================================================================================================================
    QList<double> Interpolation::linearInterpolation(const QList<double> &arguments, const QList<double> &values, const QList<double> &points)
    {
        Q_ASSERT_X(arguments.size() == values.size(), "Interpolation::linearInterpolation", "counts of arguments and values don't match");

        QList<double> interpolated_values;
        for(int i = 0; i < points.size(); ++i)
        {
            Q_ASSERT_X(arguments.first() <= points[i] && points[i] <= arguments.last(), "Interpolation::linearInterpolation", "extrapolation is needed");

            int j = 0;
            if(arguments.first() < arguments.last())
                while(!(arguments[j] <= points[i] && points[i] <= arguments[j + 1]))
                    j++;
            else
                while(!(arguments[j] >= points[i] && points[i] >= arguments[j + 1]))
                    j++;

            interpolated_values.append(((arguments[j + 1] - points[i])*values[j] + (points[i] - arguments[j])*values[j + 1])/(arguments[j + 1] - arguments[j]));
        }
        return interpolated_values;
    }
}
